#ifndef _PY_PARSER_H
#define _PY_PARSER_H

#ifdef __cplusplus
extern "C" {
#endif

/**
The Python Parser

This library provides an interface to iterate over Python abstract syntax
trees. It uses the parser from Python, hacked to work without the rest of
the Python run time.
*/

#include <stdio.h> // For FILE*

#include "Python-ast.h" // needed for mod_ty and the AST types

/**
Returns an abstract syntax tree representing the specified string. The module must be freed by using mod_free().
@param string the Python source code.
@param filename the file the source came from. If it is NULL, the string is parsed in the "Py_string_input" context.
*/
mod_ty PyASTFromString( const char* string, const char* filename );

/**
Returns an abstract syntax tree representing the specified file. The module must be freed by using mod_free().
@param handle an open file handle containing the Python source code.
@param filename the file the source came from. If it is NULL, the string is parsed in the "Py_string_input" context.
*/
mod_ty PyASTFromFile( FILE* handle, const char* filename );

// Statements
typedef void (*PyParseCallback_Function)( void* visitState, PyObject* name, arguments_ty arguments, asdl_seq* body, asdl_seq* decorators );
typedef void (*PyParseCallback_Return)( void* visitState, expr_ty value );
typedef void (*PyParseCallback_Print)( void* visitState, expr_ty destination, asdl_seq* values, bool newline );
typedef void (*PyParseCallback_Assign)( void* visitState, asdl_seq* targets, expr_ty value );
typedef void (*PyParseCallback_Expression)( void* visitState, expr_ty value );


// Expressions
typedef void (*PyParseCallback_Name)( void* visitState, identifier name, expr_context_ty context );
typedef void (*PyParseCallback_Number)( void* visitState, object number );
typedef void (*PyParseCallback_String)( void* visitState, string str );
typedef void (*PyParseCallback_Call)( void* visitState, expr_ty func, asdl_seq *args, asdl_seq *keywords, expr_ty starargs, expr_ty kwargs );


/**
Specifies callback functions for each type of statement and expression. If any of these fields are NULL, the callback will not be invoked.
*/
struct PyParse_Callbacks
{
	// Statement callbacks
	PyParseCallback_Function function;
	PyParseCallback_Return callback_return;
	PyParseCallback_Print print;
	PyParseCallback_Assign assign;
	PyParseCallback_Expression expression;
	
	// Expression callbacks
	PyParseCallback_Name name;
	PyParseCallback_Number number;
	PyParseCallback_String string;
	PyParseCallback_Call call;
};

/**
Grabs the arguments out of the statement and calls the appropriate callback.
@param visitState passed back as the first parameter to each callback.
@param callbacks the callbacks for each possible type of statement.
@param statement the statement to visit.
*/
void PyParse_Statement( void* visitState, const struct PyParse_Callbacks* callbacks, stmt_ty statement );

/**
Iterates through the collection of statements, calling the specified callbacks for each one.
@param visitState passed back as the first parameter to each callback.
@param callbacks the callbacks for each possible type of statement.
*/
void PyParse_Statements( void* visitState, const struct PyParse_Callbacks* callbacks, asdl_seq* statements );


/**
Grabs the arguments out of the expression and calls the appropriate callback.
@param visitState passed back as the first parameter to each callback.
@param callbacks the callbacks for each possible type of statement.
@param expression the expression to visit.
*/
void PyParse_Expression( void* visitState, const struct PyParse_Callbacks* callbacks, expr_ty statement );

#ifdef __cplusplus
}
#endif

#endif
